﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Dycox.Windows.Forms
{
    [DefaultProperty("Control")]
    public class ControlLabel : Label
    {
        public ControlLabel()
        {
            
        }


        private string _staticText;
        
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                _staticText = value;
            }
        }

        private Control _control;
        [TypeConverter(typeof(TargetControlConverter))]
        public Control Control
        {
            get { return _control; }
            set
            {
                if (value != null)
                {
                    if (value.GetContainerControl() != this.GetContainerControl())
                        throw new InvalidOperationException("Not in same container.");
                }

                if (_control != value)
                {

                    if (_control != null)
                        Deattach(_control);
                    _control = value;
                    if (_control != null)
                        Attach(_control);
                }
            }
        }

        private void Attach(Control control)
        {
            control.DataBindings.CollectionChanged += Control_DataBindings_CollectionChanged;
            control.BindingContextChanged += Control_BindingContextChanged;

            UpdateText();

            //control.LocationChanged += Control_LocationChanged;
            //if (control.IsHandleCreated)
            //    UpdateLocationDifference();
        }

        private void Deattach(Control control)
        {
            control.DataBindings.CollectionChanged -= Control_DataBindings_CollectionChanged;
            control.BindingContextChanged -= Control_BindingContextChanged;
            //control.LocationChanged -= Control_LocationChanged;
        }

        void Control_BindingContextChanged(object sender, EventArgs e)
        {
            UpdateText();
        }

        private void UpdateText()
        {
            if (_control != null && _control.DataBindings.Count > 0)
            {
                Binding binding = _control.DataBindings[0];
                PropertyDescriptor p;

                if (binding.BindingManagerBase != null)
                {
                    var coll = binding.BindingManagerBase.GetItemProperties();
                    p = coll[binding.BindingMemberInfo.BindingField];
                }
                else
                    p = null;

                if (p != null)
                    base.Text = p.DisplayName;
                else
                    base.Text = binding.BindingMemberInfo.BindingField;
            }
            else
                base.Text = _staticText;
        }

        //void Control_LocationChanged(object sender, EventArgs e)
        //{
        //    SyncLocation();
        //}

        //private bool _syncLocation;
        //private Point _offset;

        //private void SyncLocation()
        //{
        //    _syncLocation = true;
        //    this.Location = new Point(_control.Left - _offset.X, _control.Top - _offset.Y);
        //    _syncLocation = false;
        //}

        //protected override void OnLocationChanged(EventArgs e)
        //{
        //    base.OnLocationChanged(e);
        //    if (!_syncLocation && _control != null && _control.IsHandleCreated)
        //        UpdateLocationDifference();
        //}

        //private void UpdateLocationDifference()
        //{
        //    _offset = new Point(_control.Left - this.Left, _control.Top - this.Top);
        //}

        void Control_DataBindings_CollectionChanged(object sender, CollectionChangeEventArgs e)
        {
            UpdateText();
        }


        class TargetControlConverter : ReferenceConverter
        {
            public TargetControlConverter() : base(typeof(Control))
            {

            }

            protected override bool IsValueAllowed(ITypeDescriptorContext context, object value)
            {
                if (value is Control)
                {
                    Control c = (Control)value;
                    return (!(c is ContainerControl || c is ControlLabel || c is Button));
                }
                else
                    return base.IsValueAllowed(context, value);
            }            

            //public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            //{
            //    var coll =  base.GetStandardValues(context);

            //    List<Control> list = new List<Control>(coll.Count);
            //    foreach (Control c in list)
            //    {
            //        //if (!(c is ContainerControl || c is ControlLabel || c is Button))
            //            list.Add(c);
            //    }

            //    return new StandardValuesCollection(list);
            //}
        }
    }
}
